package com.shark.teach;


import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;


/**
 * 老版 synchronized + wait + notifyAll
 */
/*class AirCondition// 资源类
{
    private int number = 0;//有一个初始值为零的变量

    public synchronized void increment() throws InterruptedException
    {
        //1 判断
        while(number != 0)
        {
            this.wait();
        }
        //2 干活
        System.out.println(Thread.currentThread().getName()+"\t"+(++number));
        //3 通知
        this.notifyAll();
        //this.notify();
    }

    public synchronized void decrement() throws InterruptedException
    {
        //1 判断
        while(number == 0)
        {
            this.wait();
        }
        //2 干活
        System.out.println(Thread.currentThread().getName()+"\t"+(--number));
        //3 通知
        this.notifyAll();
        //this.notify();
    }
}*/

/**
 * JUC新版 , Lock + Condition.await+ signalAll
  */
class AirCondition// 资源类
{
    private int number = 0;//有一个初始值为零的变量
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();


    public void increment() throws InterruptedException
    {
        lock.lock();
        try
        {
            //1 判断
            while(number != 0)
            {
                condition.await();//this.wait();
            }
            //2 干活
            System.out.println(Thread.currentThread().getName()+"\t"+(++number));
            //3 通知
            condition.signalAll();//this.notifyAll();
        }finally {
            lock.unlock();
        }
    }

    public void decrement() throws InterruptedException
    {
        lock.lock();
        try
        {
            //1 判断
            while(number == 0)
            {
                condition.await();//this.wait();
            }
            //2 干活
            System.out.println(Thread.currentThread().getName()+"\t"+(--number));
            //3 通知
            condition.signalAll();//this.notifyAll();
        }finally {
            lock.unlock();
        }
    }
}




/**
 * @auther shark
 * @create 2024-08-05 13:48
 *
 * 两个线程，一个线程打印1-52，另一个打印字母A-Z打印顺序为12A34B...5152Z,
 * 要求用线程间通信
 *
 *
 * 有一个初始值为零的变量，现有两个线程对该变量操作，
 * 实现一个线程对变量加1，实现一个线程对变量减1,交替来10轮
 *
 *
 *  笔记：Java里面如何进行工程级别的多线程编写
 *  * 1 多线程变成模板（套路）
 *  *  高内聚低耦合前提下，线程    操作    资源类
 *
 *    2 判断   干活   通知
 *
 *    3 多线程通信中，如果存在wait方法的调用要避免，------虚假唤醒
 *
 *
 */
public class ProdConsumerDemo
{
    public static void main(String[] args)
    {
        AirCondition airCondition = new AirCondition();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    airCondition.increment();
                    try { TimeUnit.MILLISECONDS.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); }
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    airCondition.decrement();
                    try { TimeUnit.MILLISECONDS.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); }

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    airCondition.increment();
                    try { TimeUnit.MILLISECONDS.sleep(300); } catch (InterruptedException e) { e.printStackTrace(); }

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"C").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    airCondition.decrement();
                    try { TimeUnit.MILLISECONDS.sleep(400); } catch (InterruptedException e) { e.printStackTrace(); }

                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"D").start();
    }
}